package com.wuyan.web.form.helper.easyexcel;

import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;

import java.util.Comparator;
import java.util.List;

/**
 * 导出表的头部样式设定
 */

@Slf4j
public class HeadStyleWriteHandler implements CellWriteHandler {
    /**
     * 头部数据
     */
    private final List<String> head;

    /**
     * 字体大小
     */
    private short fontSize = 11;

    /**
     * 字体颜色
     */
    private short fontColor = HSSFColor.HSSFColorPredefined.BLACK.getIndex();

    /**
     * 最大列宽，width为字符个数
     */
    private final int colMaxWidth = 24;

    /**
     * 每行最大行数: 字符总宽度/colMaxWidth * 256
     */
    private final int rowMaxHeightNum = 5;

    public HeadStyleWriteHandler(List<String> head) {
        this.head = head;
    }

    /**
     * 创建单元格之前
     *
     * @param writeSheetHolder SheetHolder
     * @param writeTableHolder TableHolder
     * @param row              行
     * @param head             头
     * @param columnIndex      列索引
     * @param relativeRowIndex 相对行索引
     * @param isHead           是否头部
     */
    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder,
                                 WriteTableHolder writeTableHolder,
                                 Row row,
                                 Head head,
                                 Integer columnIndex,
                                 Integer relativeRowIndex,
                                 Boolean isHead) {
    }

    /**
     * 创建单元格之后
     *
     * @param writeSheetHolder SheetHolder
     * @param writeTableHolder TableHolder
     * @param cell             单元格
     * @param head             头部
     * @param relativeRowIndex 相对行号
     * @param isHead           是否头部
     */
    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder,
                                WriteTableHolder writeTableHolder,
                                Cell cell,
                                Head head,
                                Integer relativeRowIndex,
                                Boolean isHead) {

    }

    /**
     * 数据转换之后
     *
     * @param writeSheetHolder SheetHolder
     * @param writeTableHolder TableHolder
     * @param cellData         数据
     * @param cell             单元格
     * @param head             头部
     * @param relativeRowIndex 相对行号
     * @param isHead           是否头部
     */
    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder,
                                       WriteTableHolder writeTableHolder,
                                       CellData cellData,
                                       Cell cell,
                                       Head head,
                                       Integer relativeRowIndex,
                                       Boolean isHead) {
    }

    /**
     * 最后执行
     *
     * @param writeSheetHolder SheetHolder
     * @param writeTableHolder TableHolder
     * @param cellDataList     数据
     * @param cell             单元格
     * @param head             头部
     * @param relativeRowIndex 相对行号
     * @param isHead           是否头部
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder,
                                 WriteTableHolder writeTableHolder,
                                 List<CellData> cellDataList,
                                 Cell cell,
                                 Head head,
                                 Integer relativeRowIndex,
                                 Boolean isHead) {

        // 只处理第一行
        if (0 == cell.getRowIndex()) {
            Sheet sheet = writeSheetHolder.getSheet();

            // 设置列宽
            sheet.setColumnWidth(cell.getColumnIndex(), getColumnWidth(cell.getColumnIndex()));

            // 设置行高
            sheet.getRow(0).setHeightInPoints(getHeightInPoints());

            // 单元格设置样式
            cell.setCellStyle(createCellStyle(sheet.getWorkbook()));
        }
    }

    /**
     * 计算列宽
     *
     * @param colIndex 列索引
     * @return int
     */
    private int getColumnWidth(int colIndex) {
        return this.colMaxWidth * 256;
    }

    /**
     * 计算行高: 利用最大列宽 colMaxWidth 进行整除,再根据字体大小 fontSize 计算出最大行高
     *
     * @return int
     */
    private float getHeightInPoints() {
        String maxHead = head.stream().max(Comparator.comparingInt(String::length)).orElse(null);

        if (null == maxHead) {
            return -1;
        }

        // 字符总宽度
        int width = maxHead.getBytes().length;

        // 只要存在余数,均向上取整
        int rows = width / this.colMaxWidth;
        rows = width % this.colMaxWidth > 0 ? rows + 1 : rows;

        return (float) ((Math.min(rows, this.rowMaxHeightNum)) * (this.fontSize * 1.5));
    }

    /**
     * 设置样式
     *
     * @param workbook workbook
     */
    private CellStyle createCellStyle(Workbook workbook) {
        CellStyle cellStyle = workbook.createCellStyle();
        // 设置水平居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        // 设置垂直居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 设置下边框
        cellStyle.setBorderBottom(BorderStyle.THIN);
        // 设置上边框
        cellStyle.setBorderTop(BorderStyle.THIN);
        // 设置走边框
        cellStyle.setBorderLeft(BorderStyle.THIN);
        // 设置右边框
        cellStyle.setBorderRight(BorderStyle.THIN);
        // 自动换行
        cellStyle.setWrapText(true);

        // 设置字体
        Font font = workbook.createFont();
        // 设置字号
        font.setFontHeightInPoints(fontSize);
        // 设置是否为斜体
        font.setItalic(false);
        // 设置是否加粗
        font.setBold(false);
        // 设置字体颜色
        font.setColor(fontColor);
        cellStyle.setFont(font);

        //设置背景
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);

        return cellStyle;
    }
}
